#include "../HWJpegDecoder.h"

// 以文件系统的JPEG文件作为输入源解码

static void DMA2D_Copy_YCbCr_To_RGB(uint32_t pSrc, uint32_t pdst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize, uint32_t ChromaSampling);

void decodeJPEGFromFS(void)
{
    HWJpegDecoder *jpegDecoder = new HWJpegDecoder(&hjpeg);

    jpegDecoder->setFullInput(true);    // 读取整个文件一次性解码
    jpegDecoder->setFullOutput(true);   // 一次性输出整张图片数据

    jpegDecoder->setInputDataSource("0:/jpeg/test.jpg");

    int ret = jpegDecoder->decode();
    if (ret == HWJpegDecoder::NoError)
    {
        jpegDecoder->waitDecodeFinish();    // 阻塞等待解码完成

        HWJpegDecoder::ImageInfo &info = jpegDecoder->getImageInfo();
        // printf("height = %ld\r\n", info.height);
        // printf("width = %ld\r\n", info.width);

        // YCbCr 转RGB
        DMA2D_Copy_YCbCr_To_RGB(
            (uint32_t)jpegDecoder->getImage(),  // fullOutput时，使用这个函数获取解码后的数据
            (uint32_t)rgbBuffer,     // 存放RGB数据的缓冲区
            0,
            0,
            info.width,
            info.height,
            info.chromaSubsampling);
    }

    // jpegDecoder->reset();    // 若还需要继续解码请reset()释放内存，否则会导致内存泄漏
    
    delete jpegDecoder;     // 删除解码器
}

static void DMA2D_Copy_YCbCr_To_RGB(uint32_t pSrc, uint32_t pdst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize, uint32_t ChromaSampling)
{
	uint32_t cssMode = DMA2D_CSS_420;
	uint32_t inputLineOffset = 0;
	uint32_t destination = 0;

	/* 处理输入行偏移 */
	switch (ChromaSampling)
	{
	case JPEG_420_SUBSAMPLING:
		cssMode = DMA2D_CSS_420;
		inputLineOffset = xsize % 16;
		if (inputLineOffset != 0)
			inputLineOffset = 16 - inputLineOffset;
		break;
	case JPEG_444_SUBSAMPLING:
		cssMode = DMA2D_NO_CSS;
		inputLineOffset = xsize % 8;
		if (inputLineOffset != 0)
			inputLineOffset = 8 - inputLineOffset;
		break;
	case JPEG_422_SUBSAMPLING:
		cssMode = DMA2D_CSS_422;
		inputLineOffset = xsize % 16;
		if (inputLineOffset != 0)
			inputLineOffset = 16 - inputLineOffset;
		break;
	default:;
	}

	destination = (uint32_t)pdst + ((y * 320) + x) * 2; // 输出地址，末尾乘以2对应RGB565

	DMA2D->CR = 0x00010000UL | (1 << 9); // 存储器到存储器模式
	DMA2D->OOR = 320 - xsize;

	/* 输出格式 */
	DMA2D->OPFCCR = LTDC_PIXEL_FORMAT_RGB565 | (DMA2D_REGULAR_ALPHA << 20) | (DMA2D_RB_REGULAR << 21);

	/* 前景层输入格式 */
	DMA2D->FGPFCCR = DMA2D_INPUT_YCBCR | (DMA2D_REPLACE_ALPHA << 16) | (DMA2D_REGULAR_ALPHA << 20) | (DMA2D_RB_REGULAR << 21) | (0xFFU << 24) | (cssMode << 18);

	DMA2D->FGOR = inputLineOffset;
	DMA2D->NLR = (uint32_t)(xsize << 16) | (uint16_t)ysize;
	DMA2D->OMAR = (uint32_t)destination;
	DMA2D->FGMAR = (uint32_t)pSrc;

	DMA2D->CR |= DMA2D_CR_START; // 启动传输

	while (DMA2D->CR & DMA2D_CR_START)
		; //	等待传输完成
}